﻿/**************************************************************
 *
 * 唯一标识：8dfba7aa-02a8-44df-9680-431f16c96062
 * 命名空间：Sgr.Attachments.Services
 * 创建时间：2023/8/25 9:32:53
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

namespace Sgr.Oss.Services
{
    /// <summary>
    /// 对象存储服务接口
    /// </summary>
    public interface IOssService
    {
        #region 存储桶操作

        /// <summary>
        /// 检查存储桶是否存在
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>存在返回true，否则返回false</returns>
        Task<bool> BucketAnyAsync(
            string bucketName,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 创建存储桶
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="acl">访问权限</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>创建成功返回true，否则返回false</returns>
        Task<bool> CreateBucketAsync(
            string bucketName,
            BucketAcl acl = BucketAcl.Private,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 删除存储桶
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>删除成功返回true，否则返回false</returns>
        Task<bool> RemoveBucketAsync(
            string bucketName,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 获取所有存储桶名称
        /// </summary>
        /// <returns>存储桶名称列表</returns>
        /// <param name="cancellationToken">取消令牌</param>
        Task<IEnumerable<string>> GetBucketNamesAsync(CancellationToken cancellationToken = default);

        #endregion 存储桶操作

        #region 存储对象操作

        /// <summary>
        /// 检查存储对象是否存在
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <returns>存在返回true，否则返回false</returns>
        /// <param name="cancellationToken">取消令牌</param>
        Task<bool> ObjectsAnyAsync(
            string bucketName,
            string objectName,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 获取存储对象
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="callback">处理下载流的回调函数</param>
        /// <param name="progress">进度回调</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task GetObjectAsync(string bucketName, string objectName,
            Func<Stream, Task> callback,
            Action<ProgressInfo>? progress = null,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 获取存储对象并保存到文件
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="filePath">保存路径</param>
        /// <param name="progress">进度回调</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task GetObjectAsync(string bucketName, string objectName, string filePath,
            Action<ProgressInfo>? progress = null,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 上传对象
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="data">数据流</param>
        /// <param name="metadata">元数据</param>
        /// <param name="acl">访问权限</param>
        /// <param name="progress">进度回调</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<bool> PutObjectAsync(string bucketName,
            string objectName,
            Stream data,
            IDictionary<string, string>? metadata = null,
            ObjectAcl acl = ObjectAcl.Inherited,
            Action<ProgressInfo>? progress = null,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="metadata">元数据</param>
        /// <param name="acl">访问权限</param>
        /// <param name="progress">进度回调</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<bool> PutObjectAsync(string bucketName, string objectName, string filePath,
            IDictionary<string, string>? metadata = null,
            ObjectAcl acl = ObjectAcl.Inherited,
            Action<ProgressInfo>? progress = null,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 复制对象
        /// </summary>
        /// <param name="sourceBucketName">源存储桶</param>
        /// <param name="sourceObjectName">源对象名称</param>
        /// <param name="destBucketName">目标存储桶</param>
        /// <param name="destObjectName">目标对象名称</param>
        /// <param name="acl">访问权限</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<bool> CopyObjectAsync(string sourceBucketName, string sourceObjectName,
            string destBucketName, string? destObjectName = null,
            ObjectAcl acl = ObjectAcl.Inherited,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 删除对象
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<bool> RemoveObjectAsync(string bucketName, string objectName,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 批量删除对象
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectNames">对象名称列表</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<bool> RemoveObjectsAsync(string bucketName, IEnumerable<string> objectNames,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 获取对象元数据
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<ObjectMetadata> GetObjectMetadataAsync(string bucketName, string objectName,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 列举对象
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="prefix">前缀</param>
        /// <param name="continuationToken">延续标记</param>
        /// <param name="maxKeys">最大返回数量</param>
        /// <param name="useHierarchy">控制是否使用层级结构</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<ListObjectsResult> ListObjectsAsync(string bucketName,
            string? prefix = null,
            string? continuationToken = null,
            int maxKeys = 1000,
            bool useHierarchy = true,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 获取对象访问URL（仅支持GET访问）
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="expiry">过期时间</param>
        /// <param name="cancellationToken">取消令牌</param>
        Task<string> GetPresignedGetUrlAsync(string bucketName, string objectName,
            TimeSpan expiry,
            CancellationToken cancellationToken = default);

        /// <summary>
        /// 获取用于上传的预签名URL
        /// </summary>
        /// <param name="bucketName">存储桶名称</param>
        /// <param name="objectName">对象名称</param>
        /// <param name="expiry">过期时间</param>
        /// <param name="contentType">内容类型</param>
        /// <param name="metadata">用户自定义元数据</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>预签名URL</returns>
        /// <remarks>
        /// 此方法生成的URL支持HTTP PUT方法上传对象。
        /// 可以通过contentType参数指定上传内容的类型。
        /// 可以通过metadata参数指定对象的自定义元数据。
        /// 可以通过acl参数指定对象的访问权限。
        /// </remarks>
        Task<string> GetPresignedPutUrlAsync(
            string bucketName,
            string objectName,
            TimeSpan expiry,
            string? contentType = null,
            IDictionary<string, string>? metadata = null,
            CancellationToken cancellationToken = default);

        #endregion 存储对象操作

        //#region 分片上传

        ///// <summary>
        ///// 初始化分片上传
        ///// </summary>
        ///// <param name="bucketName">存储桶名称</param>
        ///// <param name="objectName">对象名称</param>
        ///// <param name="metadata">元数据</param>
        ///// <param name="acl">访问权限</param>
        ///// <param name="cancellationToken">取消令牌</param>
        //Task<string> InitiateMultipartUploadAsync(string bucketName, string objectName,
        //    IDictionary<string, string>? metadata = null,
        //    ObjectAcl acl = ObjectAcl.Inherited,
        //    CancellationToken cancellationToken = default);

        ///// <summary>
        ///// 上传分片
        ///// </summary>
        ///// <param name="uploadId">上传ID</param>
        ///// <param name="partNumber">分片号</param>
        ///// <param name="data">分片数据</param>
        ///// <param name="progress">进度回调</param>
        ///// <param name="cancellationToken">取消令牌</param>
        //Task<PartInfo> UploadPartAsync(string uploadId, int partNumber, Stream data,
        //    Action<ProgressInfo>? progress = null,
        //    CancellationToken cancellationToken = default);

        ///// <summary>
        ///// 完成分片上传
        ///// </summary>
        ///// <param name="uploadId">上传ID</param>
        ///// <param name="parts">分片信息</param>
        ///// <param name="cancellationToken">取消令牌</param>
        //Task<bool> CompleteMultipartUploadAsync(string uploadId,
        //    IEnumerable<PartInfo> parts,
        //    CancellationToken cancellationToken = default);

        ///// <summary>
        ///// 取消分片上传
        ///// </summary>
        ///// <param name="uploadId">上传ID</param>
        ///// <param name="cancellationToken">取消令牌</param>
        //Task<bool> AbortMultipartUploadAsync(string uploadId,
        //    CancellationToken cancellationToken = default);

        //#endregion 分片上传
    }
}